package dongze.com.ckdj;

import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.util.Log;

import com.tencent.bugly.Bugly;
import com.tencent.bugly.crashreport.CrashReport;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import dongze.com.ckdj.dagger.DataStore;
import dongze.com.ckdj.dagger.component.AppComponent;
import dongze.com.ckdj.dagger.component.DaggerAppComponent;
import dongze.com.ckdj.dagger.component.SectionComponent;
import dongze.com.ckdj.dagger.component.UserComponent;
import dongze.com.ckdj.dagger.component.VehicleComponent;
import dongze.com.ckdj.dagger.module.MainModule;
import dongze.com.ckdj.service.ImageUploadService;
import dongze.com.ckdj.util.MyLog;
import dongze.com.ckdj.util.Util;
import io.reactivex.functions.Consumer;
import io.reactivex.plugins.RxJavaPlugins;

/**
 * Created by Administrator on 2017/7/18.
 */
public class CKDJApplication extends Application {
    private static final String TAG = CKDJApplication.class.getSimpleName();
    AppComponent component;
    static Map<Class, Object> components = new HashMap<>();
    List<SoftReference<Activity>> activities = new ArrayList();
    @Inject
    DataStore dataStore;

    @Override
    public void onCreate() {
        super.onCreate();
        Logger log = LoggerFactory.getLogger(CKDJApplication.class);
        log.debug("logback");
        log = LoggerFactory.getLogger(MainActivity.class);
        log.debug("logback_main");
        MyLog.e("timber", "timber");
        MyLog.d(TAG, "onCreate: ");

        if (!BuildConfig.DEBUG)
            Bugly.init(getApplicationContext(), "680d575b46", BuildConfig.DEBUG);

        component = DaggerAppComponent.builder()
                .mainModule(new MainModule(this))
                .build();
        component.inject(this);
        components.put(AppComponent.class, component);
        startService(new Intent(this, ImageUploadService.class));

        // try to restore data from saved state
        try {
            UserComponent userComponent = Util.buildUserComponent(component, dataStore);
            addComponent(UserComponent.class, userComponent);
            SectionComponent sectionComponent = Util.buildSectionComponent(userComponent, dataStore);
            addComponent(SectionComponent.class, sectionComponent);
            VehicleComponent vehicleComponent = Util.buildVehicleComponent(sectionComponent, dataStore);
            addComponent(VehicleComponent.class, vehicleComponent);
        } catch (Exception e) {
        }

        RxJavaPlugins.setErrorHandler(new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                MyLog.e(TAG, "RxJava unhandled: ", throwable);
            }
        });
    }

    @Override
    public void onTerminate() {
        MyLog.d(TAG, "onTerminate: ");
        super.onTerminate();
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        MyLog.d(TAG, "onLowMemory: ");
    }

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        MyLog.d(TAG, "onTrimMemory: " + level);
    }

    public AppComponent getAppComponent() {
        return component;
    }

    // TODO: 2017/8/18 clear component when not in scope, or cause data mismatch on enter app again
    public <T> void addComponent(Class<T> clazz, T component) {
        MyLog.d(TAG, "addComponent: " + clazz + ":" + component);
        components.put(clazz, component);
    }

    public <T> T getComponent(Class<T> clazz) {
        try {
            return (T) components.get(clazz);
        } catch (Exception e) {
            MyLog.e(TAG, "getAppComponent: ", e);
        }

        return null;
    }

    public void addActivity(Activity activity) {
        MyLog.v(TAG, "add activity " + activity);
        activities.add(new SoftReference<Activity>(activity));
    }

    public void removeAxctivity(Activity activity) {
        MyLog.v(TAG, "remove activity " + activity);
        for (SoftReference<Activity> a :
                activities) {
            Activity ac = a.get();

            if (ac != activity) {
                activities.remove(a);
                break;
            }
        }
    }

    public void finishAllActtivity() {
        for (SoftReference<Activity> a :
                activities) {
            Activity ac = a.get();
            if (ac != null) {
                MyLog.v(TAG, "finish all activity " + ac);
                ac.finish();
            }
        }
    }
}
